package cn.bytets.rpc.api.balance;

import cn.bytets.rpc.api.invoke.Invocation;
import cn.bytets.rpc.api.invoke.Invoker;
import cn.bytets.rpc.common.URL;

import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 负载均衡-随机
 */
public class RandomLoadBalance  extends AbstractLoadBalance{

    public final static String BALANCE_NAME = "random";

    @Override
    protected  Invoker doSelect(List<Invoker> invokers, URL url, Invocation invocation) {
        int length = invokers.size();
        /**
         * 所有的Invoker的权重是否相同
         */
        boolean sameWeight = true;
        /**
         * 每个调用者的权重
         */
        int[] weights = new int[length];
        /**
         * 获取第一个Invoker的权重
         */
        int firstWeight = getWeight(invokers.get(0), invocation);

        weights[0] = firstWeight;
        /**
         * 权重总和
         */
        int totalWeight = firstWeight;

        for (int i = 1; i < length; i++) {
            int weight = getWeight(invokers.get(i), invocation);
            // save for later use
            weights[i] = weight;
            // Sum
            totalWeight += weight;
            /**
             * 这里表示权重不一样(没有配置权重则默认都是100)
             */
            if (sameWeight && weight != firstWeight) {
                sameWeight = false;
            }
        }

        if (totalWeight > 0 && !sameWeight) {
            /**
             * 如果（不是每个调用程序都有相同的权重和至少一个调用者的权重>0），则根据 totalWeight 随机选择
             */
            int offset = ThreadLocalRandom.current().nextInt(totalWeight);
            // 根据随机值返回调用程序。
            for (int i = 0; i < length; i++) {
                offset -= weights[i];
                if (offset < 0) {
                    return invokers.get(i);
                }
            }
        }
        /**
         * 这里则表示所有接口都没有配置权重,或者配置权重不合规
         * ThreadLocalRandom.current() 为java提供的当前线程共享的随机类
         */
        return invokers.get(ThreadLocalRandom.current().nextInt(length));
    }
}
